<script setup lang="ts">
import ClausePanel from './components/ClausePanel.vue'
import HelpsPanel from './components/HelpsPanel.vue'
import ShipmentPanel from './components/ShipmentPanel.vue'
import SkuPanel from './components/SkuPanel.vue'
// 导入骨架屏组件
import { toRef, ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import type { GoodsSku, SkuEvent } from '@/components/vk-data-goods-sku-popup/types'
import { getGoodsById, getGoodsRelevant } from '@/services/goods'
import { postMemberCart } from '@/services/cart'
import { useAddressStore } from '@/stores'
import PageSkeleton from './components/PageSkeleton.vue'
import type { GoodsResult } from '@/types/goods'
import type { GoodsItem } from '@/types/global'

// 返回上一页
const goBack = () => {
  uni.navigateBack({})
}

// 跳转到购物车页面
const goCart = () => {
  uni.navigateTo({ url: '/pages/cart/default' })
}

// 弹窗
const popup = ref<{
  open(): void
  close(): void
}>()

type Layer = 'helps' | 'sku' | 'shipment' | 'clause'
const layer = ref<Layer>('helps')

// 显示弹层
const showHalfDialog = (layerName: Layer) => {
  layer.value = layerName
  popup.value!.open()
}
// 关闭弹层
const hideHalfDialog = () => {
  popup.value!.close()
}
// ------------------ 自己写的代码 ----------------------------
const { safeAreaInsets } = uni.getSystemInfoSync()
const query = defineProps<{
  id: string
}>()

const goods = ref({} as GoodsResult)
const goodsRelevants = ref<GoodsItem[]>([])

// 根据商品 id 获取商品详情
const getGoodsData = async () => {
  const res = await getGoodsById(query.id)
  goods.value = res.result
  // 🎯🎯🎯 基于后端返回的数据，处理成 SKU 组件所需的数据格式
  goodsSku.value = {
    _id: goods.value.id,
    name: goods.value.name,
    goods_thumb: goods.value.mainPictures[0],
    sku_list: goods.value.skus.map((item) => {
      return {
        _id: item.id,
        goods_id: goods.value.id,
        goods_name: goods.value.name,
        image: goods.value.mainPictures[0],
        price: item.price * 100, // 注意乘 100
        sku_name_arr: item.specs.map((v) => v.valueName),
        stock: item.inventory,
      }
    }),
    spec_list: goods.value.specs.map((item) => {
      return {
        name: item.name,
        list: item.values.map((v) => ({ name: v.name })),
      }
    }),
  }
}

// 根据商品 id 获取相关推荐商品列表
const getGoodsRelevantData = async () => {
  const res = await getGoodsRelevant({ id: query.id, limit: 6 })
  goodsRelevants.value = res.result
}

// 页面加载
onLoad(() => {
  getGoodsData()
  getGoodsRelevantData()
})

// 当前 Swiper 的下标
const current = ref(0)
// 🔔 轮播图切换时会触发 change 事件，常用于自定义轮播图指示器
const swiperChange = (ev: UniHelper.SwiperOnChangeEvent) => {
  // 保存当前轮播图下标
  current.value = ev.detail.current
}

// 点击大图预览
const previewImage = (url: string) => {
  uni.previewImage({
    current: url,
    urls: goods.value.mainPictures,
  })
}

// ------------------ SKU 业务开始 -----------------------
// 是否显示 SKU 组件
const isShowSku = ref(false)
// SKU 组件按钮模式，通过枚举提升代码可读性
const enum SkuMode {
  /**
   * 都显示
   */
  Both = 1,
  /**
   * 只显示购物车
   */
  Cart = 2,
  /**
   * 只显示立即购买
   */
  Buy = 3,
}
// SKU 组件按钮模式
const skuMode = ref(SkuMode.Both)
// SKU 组件数据源
const goodsSku = ref({} as GoodsSku)

// 点击规格，点击加入购物车，点击立即购买，通过 mode 参数区别按钮模式
const openSkuPopup = (mode: SkuMode) => {
  // 显示什么按钮模式
  skuMode.value = mode
  // 显示 SKU 组件
  isShowSku.value = true
}

// 准备一个 ref 响应式数据，用于存储 sku 组件实例
const skuRef = ref()
// 用于 SKU 展示的规格文本
const selectArrText = computed(() => skuRef.value?.selectArr.join(' ').trim())
// 🟠加入购物车
const onAddCart = async (ev: SkuEvent) => {
  // 调用接口加入购物车
  await postMemberCart({ skuId: ev._id, count: ev.buy_num })
  // 成功提示
  uni.showToast({ title: '添加成功' })
  // 关闭 SKU 组件
  isShowSku.value = false
}

const addressStore = useAddressStore()
// 🟢立即购买
const onBuyNow = (ev: SkuEvent) => {
  // 获取立即购买接口所需的 3 的参数，用于页面传参
  const skuId = ev._id
  const count = ev.buy_num
  const addressId = addressStore.selectedAddress.id
  // 多个页面参数需要通过 & 链接，格式 ?key=value&key2=value2
  uni.navigateTo({
    url: `/pages/order/create?skuId=${skuId}&count=${count}&addressId=${addressId}`,
  })
  // 关闭 SKU 组件
  isShowSku.value = false
}
</script>

<template>
  <XtxBack />
  <!-- 骨架屏组件 与 正常展示的结构 互斥 -->
  <PageSkeleton v-if="!goods.id" />
  <!-- 正常展示的结构用 template 编组起来，通过 v-else 互斥 -->
  <template v-else>
    <scroll-view
      scroll-y
      enhanced
      :bounces="false"
      :show-scrollbar="false"
      scroll-with-animation
      class="viewport"
      id="scrollView"
    >
      <view :style="{ height: safeAreaInsets?.top + 'px' }"></view>
      <!-- 商品信息 -->
      <view class="goods anchor" data-anchor-index="0">
        <view class="preview">
          <swiper @change="swiperChange" circular>
            <swiper-item v-for="(item, index) in goods.mainPictures" :key="index">
              <image @tap="previewImage(item)" :src="item" />
            </swiper-item>
          </swiper>
          <view class="indicator">
            <text class="current">{{ current + 1 }}</text>
            <text class="split">/</text>
            <text class="total">{{ goods.mainPictures?.length }}</text>
          </view>
        </view>

        <view class="meta">
          <view class="price">
            <text class="symbol">¥</text>
            <text class="number">{{ goods.price }}</text>
          </view>
          <view class="name ellipsis">
            {{ goods.name }}
          </view>
          <view class="remarks"> {{ goods.desc }} </view>
        </view>
        <view class="related">
          <view @tap="openSkuPopup(SkuMode.Both)" class="item arrow">
            <text class="label">选择</text>
            <text class="text ellipsis">
              {{ selectArrText || '请选择商品规格' }}
            </text>
          </view>
          <!-- <view @tap="showHalfDialog('sku')" class="item arrow">
            <text class="label">选择</text>
            <text class="text ellipsis">白色 红外体温计 1件</text>
          </view> -->
          <view @tap="showHalfDialog('shipment')" class="item arrow">
            <text class="label">送至</text>
            <text class="text ellipsis">北京市顺义区京顺路9号黑马程序员</text>
          </view>
          <view @tap="showHalfDialog('clause')" class="item arrow">
            <text class="label">服务</text>
            <text class="text ellipsis">无忧退 快速退款 免费包邮</text>
          </view>
        </view>
      </view>
      <!-- 商品详情 -->
      <view class="detail panel anchor" data-anchor-index="2">
        <view class="title">
          <text>详情</text>
        </view>
        <view class="content">
          <view class="properties">
            <!-- 商品详情属性 -->
            <view class="item" v-for="item in goods.details?.properties" :key="item.name">
              <text class="label">{{ item.name }}</text>
              <text class="value">{{ item.value }}</text>
            </view>
          </view>

          <!-- 商品详情图片 -->
          <image
            mode="widthFix"
            v-for="(item, index) in goods.details?.pictures"
            :key="index"
            :src="item"
          ></image>
        </view>
      </view>
      <!-- 常见问题 -->
      <view class="help arrow" @tap="showHalfDialog('helps')">
        <text class="icon-help"></text>
        <navigator hover-class="none">常见问题</navigator>
      </view>
      <!-- 推荐 -->
      <view class="recommend panel anchor" data-anchor-index="3">
        <view class="title">
          <text>推荐</text>
        </view>
        <view class="content">
          <navigator
            v-for="item in goodsRelevants"
            :key="item.id"
            :url="`/pages/goods/index?id=${item.id}`"
            hover-class="none"
          >
            <image class="image" mode="aspectFit" :src="item.picture"></image>
            <view class="name ellipsis">
              {{ item.name }}
            </view>
            <view class="price">
              <text class="symbol">¥</text>
              <text class="number">{{ item.price }}</text>
            </view>
          </navigator>
        </view>
      </view>
    </scroll-view>

    <!-- 用户操作 -->
    <view class="toolbar" :style="{ paddingBottom: safeAreaInsets?.bottom + 'px' }">
      <view class="icons">
        <button class="collect"><text class="icon-heart"></text>收藏</button>
        <button class="contact" open-type="contact"><text class="icon-handset"></text>客服</button>
        <button class="cart" @tap="goCart"><text class="icon-cart"></text>购物车</button>
      </view>
      <view class="buttons">
        <view @tap="openSkuPopup(SkuMode.Cart)" data-button-type="cart" class="addcart">
          加入购物车
        </view>
        <view @tap="openSkuPopup(SkuMode.Buy)" data-button-type="payment" class="payment">
          立即购买
        </view>
      </view>
    </view>

    <uni-popup type="bottom" ref="popup" background-color="#fff" safe-area is-mask-click>
      <view class="popup-root">
        <text @tap="hideHalfDialog" class="close icon-close"></text>
        <SkuPanel button-type="" v-if="layer === 'sku'" />
        <ShipmentPanel v-if="layer === 'shipment'" />
        <ClausePanel v-if="layer === 'clause'" />
        <HelpsPanel v-if="layer === 'helps'" />
      </view>
    </uni-popup>

    <!-- SKU 弹窗组件 -->
    <vk-data-goods-sku-popup
      v-model="isShowSku"
      :mode="skuMode"
      :localdata="goodsSku"
      ref="skuRef"
      @add-cart="onAddCart"
      @buy-now="onBuyNow"
      add-cart-background-color="#FFA868"
      buy-now-background-color="#28BA9A"
      price-color="#cf4444"
      :actived-style="{
        color: 'rgba(39, 186, 155)',
        borderColor: 'rgba(39, 186, 155)',
        backgroundColor: 'rgba(39, 186, 155, 0.1)',
      }"
    />
  </template>
</template>

<style>
page {
  height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* 自定义导航栏 */
.navbar {
  width: 750rpx;
  background-color: #fff;

  position: fixed;
  top: 0;
  left: 0;
  z-index: 9;
}

.navbar .search {
  height: 40px;
  padding: 1px 110px 0 50px;
}

.navbar .search .input {
  height: 62rpx;
  border-radius: 60rpx;
  font-size: 26rpx;
  color: #8b8b8b;
  background-color: #f3f4f4;
  position: relative;
}

.navbar .search .input::before {
  position: absolute;
  left: 24rpx;
  top: 50%;

  color: #b7b7b7;
  font-size: 28rpx;
  transform: translateY(-50%);
}

.navbar .wrap {
  position: relative;
}

.navbar .back {
  position: absolute;
  left: 10px;
  top: 2px;
  z-index: 9;

  display: flex;
  justify-content: center;
  align-items: center;
  width: 60rpx;
  height: 60rpx;
  border-radius: 50%;
  font-size: 23px;
  color: #191919;
  /* color: #fff; */
  /* background-color: rgba(0, 0, 0, 0.4); */
}

.navbar .tabs {
  display: flex;
  justify-content: space-evenly;
  border-bottom: 1rpx solid #eaeaea;
}

.navbar .tabs text {
  display: block;
  padding: 10rpx 10rpx 16rpx;
  font-size: 28rpx;
  position: relative;
}

.navbar .tabs .active {
  color: #27ba9b;
  font-weight: 500;
}

.navbar .tabs .active::after {
  content: '';
  position: absolute;
  left: 18rpx;
  right: 20rpx;
  bottom: 14rpx;
  height: 4rpx;
  background-color: #27ba9b;
}

.viewport {
  background-color: #f4f4f4;
}

.panel {
  margin-top: 20rpx;
  background-color: #fff;
}

.panel .title {
  display: flex;
  justify-content: space-between;
  align-items: center;

  height: 90rpx;
  line-height: 1;
  padding: 30rpx 60rpx 30rpx 6rpx;
  position: relative;
}

.panel .title text {
  padding-left: 10rpx;
  font-size: 28rpx;
  color: #333;
  font-weight: 600;
  border-left: 4rpx solid #27ba9b;
}

.panel .title navigator {
  font-size: 24rpx;
  color: #666;
}

.arrow::after {
  position: absolute;
  top: 50%;
  right: 30rpx;

  content: '\e6c2';
  color: #ccc;
  font-family: 'erabbit' !important;
  font-size: 32rpx;
  transform: translateY(-50%);
}

/* 商品信息 */
.goods {
  background-color: #fff;
}

.goods .preview {
  height: 750rpx;
  position: relative;
}

.goods .preview .indicator {
  height: 40rpx;
  padding: 0 24rpx;
  line-height: 40rpx;
  border-radius: 30rpx;
  color: #fff;
  font-family: Arial, Helvetica, sans-serif;
  background-color: rgba(0, 0, 0, 0.3);

  position: absolute;
  bottom: 30rpx;
  right: 30rpx;
}

.goods .indicator .current {
  font-size: 26rpx;
}

.goods .indicator .split {
  font-size: 24rpx;
  margin: 0 1rpx 0 2rpx;
}

.goods .indicator .total {
  font-size: 24rpx;
}

.goods .meta {
  position: relative;
  border-bottom: 1rpx solid #eaeaea;
}

.goods .meta .price {
  height: 130rpx;
  padding: 25rpx 30rpx 0;
  color: #fff;
  font-size: 34rpx;
  box-sizing: border-box;
  background-color: #35c8a9;
}

.goods .meta .number {
  font-size: 56rpx;
}

.goods .meta .brand {
  width: 160rpx;
  height: 80rpx;
  overflow: hidden;

  position: absolute;
  top: 26rpx;
  right: 30rpx;
}

.goods .meta .name {
  max-height: 88rpx;
  line-height: 1.4;
  margin: 20rpx;
  font-size: 32rpx;
  color: #333;
}

.goods .meta .remarks {
  line-height: 1;
  padding: 0 20rpx 30rpx;
  font-size: 24rpx;
  color: #cf4444;
}

.goods .related {
  padding-left: 20rpx;
}

.goods .related .item {
  height: 90rpx;
  padding-right: 60rpx;
  border-bottom: 1rpx solid #eaeaea;
  font-size: 26rpx;
  color: #333;
  position: relative;
  display: flex;
  align-items: center;
}

.goods .related .item:last-child {
  border-bottom: 0 none;
}

.goods .related .label {
  width: 60rpx;
  color: #898b94;
  margin: 0 16rpx 0 10rpx;
}

.goods .related .text {
  flex: 1;
  -webkit-line-clamp: 1;
}

/* 商品评论 */
.comments {
  padding-left: 20rpx;
}

.comments .comment {
  padding: 24rpx 40rpx 24rpx 10rpx;
  border-top: 1rpx solid #eaeaea;
}

.comments .caption {
  height: 60rpx;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.comments .user {
  font-size: 26rpx;
  color: #333;
  display: flex;
  align-items: center;
}

.comments .caption .avatar {
  width: 60rpx;
  height: 60rpx;
  margin-right: 20rpx;
  border-radius: 50%;
}

.comments .rating {
  width: 144rpx;
  height: 24rpx;
  background-image: url(https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/images/rating_off.png);
  background-size: contain;
}

.comments .rating .rank {
  height: 100%;
  background-image: url(https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/images/rating_on.png);
  background-size: 144rpx 24rpx;
}

.comments .content .text {
  line-height: 1.4;
  margin-top: 24rpx;
  font-size: 24rpx;
  color: #333;
}

.comments .pictures {
  display: flex;
  flex-wrap: wrap;
  margin: 20rpx 0 0 1rpx;
}

.comments .picture {
  width: 150rpx;
  height: 150rpx;
  margin-right: 27rpx;
}

.comments .picture:last-child {
  margin-right: 0;
}

.comments .content .extra {
  display: flex;
  justify-content: space-between;
  margin: 20rpx 1rpx 0 0;
  font-size: 22rpx;
  color: #666;
}

/* 类似商品 */
.similar {
  margin-top: 20rpx;
}

.similar .bar {
  display: flex;
  align-items: center;
  height: 90rpx;
  font-size: 28rpx;
  color: #333;
  background-color: #fff;
}

.similar .bar text {
  flex: 1;
  text-align: center;
  position: relative;
}

.similar .bar .active::after {
  content: '';
  display: block;
  width: 60rpx;
  height: 4rpx;
  background-color: #27ba9b;
  transform: translateX(-50%);
  position: absolute;
  left: 50%;
  bottom: -5rpx;
}

.similar .content {
  padding-top: 20rpx;
  background-color: #f4f4f4;
  white-space: nowrap;
}

.similar .content navigator {
  display: inline-block;
  width: 200rpx;
  height: 270rpx;
  padding: 15rpx 15rpx 0;
  margin-right: 15rpx;
  background-color: #fff;
  border-radius: 6rpx;
}

.similar .content navigator:first-child {
  margin-left: 15rpx;
}

.similar .content image {
  height: 172rpx;
}

.similar .content .name {
  max-height: 64rpx;
  line-height: 1.2;
  margin-top: 10rpx;
  font-size: 24rpx;
  color: #333;
  -webkit-line-clamp: 1;
}

.similar .content .price {
  font-size: 18rpx;
  color: #cf4444;
}

.similar .content .number {
  font-size: 24rpx;
  margin-left: 2rpx;
}

/* 商品详情 */
.detail {
  padding-left: 20rpx;
}

.detail .content {
  margin-left: -20rpx;
}

.detail .properties {
  padding: 0 20rpx;
  margin-bottom: 30rpx;
}

.detail .properties .item {
  display: flex;
  line-height: 2;
  padding: 10rpx;
  font-size: 26rpx;
  color: #333;
  border-bottom: 1rpx dashed #ccc;
}

.detail .properties .label {
  width: 200rpx;
}

.detail .properties .value {
  flex: 1;
}

/* 常见问题 */
.help {
  display: flex;
  align-items: center;
  padding: 20rpx 0 20rpx 20rpx;
  margin-top: 20rpx;
  font-size: 28rpx;
  color: #333;
  background-color: #fff;
  position: relative;
}

.help .icon-help {
  font-size: 34rpx;
  margin-right: 6rpx;
  color: #ffa868;
}

/* 商品推荐 */
.recommend {
  padding-left: 20rpx;
}

.recommend .content {
  padding: 0 20rpx 20rpx;
  margin-left: -20rpx;
  background-color: #f4f4f4;
  overflow: hidden;
}

.recommend .content navigator {
  width: 345rpx;
  padding: 24rpx 20rpx 20rpx;
  margin: 20rpx 20rpx 0 0;
  border-radius: 10rpx;
  background-color: #fff;
  float: left;
}

.recommend navigator:nth-child(even) {
  margin-right: 0;
}

.recommend .content .image {
  height: 260rpx;
}

.recommend .content .name {
  height: 80rpx;
  margin: 10rpx 0;
  font-size: 26rpx;
  color: #262626;
}

.recommend .content .price {
  line-height: 1;
  font-size: 20rpx;
  color: #cf4444;
}

.recommend .content .number {
  font-size: 26rpx;
  margin-left: 2rpx;
}

/* 底部工具栏 */
.toolbar {
  height: 100rpx;
  padding: 0 20rpx;
  border-top: 1rpx solid #eaeaea;
  display: flex;
  justify-content: space-between;
  align-items: center;
  box-sizing: content-box;
}

.toolbar .buttons {
  display: flex;
}

.toolbar .buttons > view {
  width: 220rpx;
  text-align: center;
  line-height: 72rpx;
  font-size: 26rpx;
  color: #fff;
  border-radius: 72rpx;
}

.toolbar .buttons .addcart {
  background-color: #ffa868;
}

.toolbar .buttons .payment {
  background-color: #27ba9b;
  margin-left: 20rpx;
}

.toolbar .icons {
  padding-right: 10rpx;
  display: flex;
  align-items: center;
  justify-content: space-evenly;
  flex: 1;
}

.toolbar .icons button {
  text-align: center;
  line-height: 1.4;
  padding: 0;
  border-radius: 0;
  font-size: 20rpx;
  color: #333;
  background-color: #fff;
}

.toolbar .icons text {
  display: block;
  font-size: 34rpx;
}
</style>
